﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Streambolics.Gui;

namespace Streambolics.App
{
    /// <summary>
    ///     The main form of a Streambolics application.
    /// </summary>

    public partial class AppForm : StandardForm
    {
        private ModuleManager _GlobalModuleManager;
        private LogFileWriter _LogFileWriter;
        private SystemMenu _SystemMenu;

        private bool _Exiting = false;
        private bool _WarnMinimize = true;
        private bool _AlreadyClosing = false;

        public AppForm ()
        {
            InitializeComponent ();

            _LogFileWriter = new LogFileWriter ("EventLog.txt");
            _GlobalModuleManager = new ModuleManager ();
            _SystemMenu = new SystemMenu (this);
        }

        /// <summary>
        ///     Whether this application is a server, or a user application.
        /// </summary>
        /// <returns>
        ///     True if the application should act as a server, false if
        ///     the application should act as a user application.
        /// </returns>
        /// <remarks><para>
        ///     An application should override this function to return the
        ///     appropriate value.
        /// </para><para>
        ///     The return value of this function affects how the application
        ///     behaves globally. Every specific behaviour of the application
        ///     can be further configured throught the ShouldXxx methods in the
        ///     "Expected behaviour" section.
        /// </para></remarks>

        protected virtual bool IsServer ()
        {
            return false;
        }

        #region Expected Behaviour

        /// <summary>
        ///     Whether a close request (from the close box of the window)
        ///     should in fact simply minimize the application.
        /// </summary>
        /// <returns>
        ///     True if a close should only minimize the application.
        ///     False if a close should exit the application.
        /// </returns>

        protected virtual bool ShouldMinimizeOnClose ()
        {
            return IsServer();
        }

        protected virtual bool ShouldShowSystrayNormal ()
        {
            return false;
        }

        protected virtual bool ShouldShowSystrayMinimized ()
        {
            return IsServer ();
        }

        protected virtual bool ShouldShowTaskbarNormal ()
        {
            return true;
        }

        protected virtual bool ShouldShowTaskbarMinimized ()
        {
            return !IsServer ();
        }

        protected virtual bool ShouldMinimizeOnStart ()
        {
            return IsServer ();
        }

        protected virtual bool ShouldBalloonOnMinimize ()
        {
            return true;
        }

        private bool ShouldDialogOnMinimize ()
        {
            return false;
        }

        #endregion

        #region Inherited Event Handlers

        protected override void OnLoad (EventArgs e)
        {
            base.OnLoad (e);

            RegisterAsMain ();

            MasterComputingModule.MasterModule.StatusChanged += new ComputingModuleStatusChangedEventHandler (MasterModule_StatusChanged);
            MasterComputingModule.MasterModule.ModuleStopping += new CancelEventHandler (MasterModule_ModuleStopping);

            _GlobalModuleManager.Start ();
            _LogFileWriter.Start ();

            // TODO : load plugins

            notifyIcon.Icon = Icon;
            notifyIcon.Text = Text;

            if (ShouldMinimizeOnClose ())
            {
                _SystemMenu.Append ("Exit Server").Click += new EventHandler (ExitServer_Click);
            }

            UpdateVisibility ();
            if (ShouldMinimizeOnStart ())
            {
                WindowState = FormWindowState.Minimized;
            }
        }

        protected override void OnFormClosing (FormClosingEventArgs e)
        {
            if (e.Cancel)
            {
                return;
            }

            _AlreadyClosing = true;
            try
            {
                if (MinimizeOnClose (e))
                {
                    _WarnMinimize = true;
                    WindowState = FormWindowState.Minimized;
                    e.Cancel = true;
                }
                else if (!MasterComputingModule.MasterModule.IsIdle)
                {
                    if (!MasterComputingModule.MasterModule.IsStopping)
                    {
                        MasterComputingModule.MasterModule.Stop ();
                    }
                    e.Cancel = MasterComputingModule.MasterModule.IsStopping;
                }

                if (!e.Cancel)
                {
                    base.OnFormClosing (e);
                }
            }
            finally
            {
                _AlreadyClosing = false;
            }
        }

        protected override void OnSizeChanged (EventArgs e)
        {
            base.OnSizeChanged (e);
            UpdateVisibility ();
        }

        #endregion

        /// <summary>
        ///     Whether we should minimize instead of close the window.
        /// </summary>
        /// <returns>
        ///     True if a close should trigger a minimize, false if a close
        ///     should really close the app.
        /// </returns>

        private bool MinimizeOnClose (FormClosingEventArgs e)
        {
            return e.CloseReason == CloseReason.UserClosing
                && ShouldMinimizeOnClose ()
                && !_Exiting;
        }

        protected virtual bool ConfirmExit ()
        {
            return true;
        }

        private void UpdateVisibility ()
        {
            if (WindowState == FormWindowState.Minimized)
            {
                ShowInTaskbar = ShouldShowTaskbarMinimized ();
                notifyIcon.Visible = ShouldShowSystrayMinimized ();
                menuItem_NotifyIcon_Restore.Enabled = true;
            }
            else
            {
                ShowInTaskbar = ShouldShowTaskbarNormal ();
                notifyIcon.Visible = ShouldShowSystrayNormal ();
                menuItem_NotifyIcon_Restore.Enabled = false;
            }

            if (!ShowInTaskbar && notifyIcon.Visible && _WarnMinimize)
            {
                _WarnMinimize = false;
                WarnUserAboutSystray ();
            }
        }

        protected virtual string SystrayWarning ()
        {
            StringBuilder sb = new StringBuilder ();

            sb.AppendFormat ("{0} has minimized to the System Tray.", Text);

            if (ShouldMinimizeOnClose ())
            {
                sb.AppendFormat ("\r\nTo exit {0}, right click the icon and chose Exit", Text);
            }
            return sb.ToString ();
        }

        private void WarnUserAboutSystray ()
        {
            if (ShouldBalloonOnMinimize ())
            {
                notifyIcon.ShowBalloonTip (5000, Text, SystrayWarning (), ToolTipIcon.Info);
            }

            if (ShouldDialogOnMinimize ())
            {
                MessageBox.Show (SystrayWarning());
            }
        }

        protected void RestoreApplication ()
        {
            WindowState = FormWindowState.Normal;
        }

        protected void ExitApplication ()
        {
            if (!_AlreadyClosing)
            {
                _Exiting = true;
                Close ();
            }
        }

        protected virtual void DisplayGlobalStatus (string aStatus)
        {
        }

        protected void ShowLogFile ()
        {
            _LogFileWriter.ShowFile ();
        }
        #region Component Event Handlers

        private void menuItem_NotifyIcon_Exit_Click (object sender, EventArgs e)
        {
            ExitApplication ();
        }

        private void menuItem_NotifyIcon_Restore_Click (object sender, EventArgs e)
        {
            RestoreApplication ();
        }

        private void notifyIcon_MouseDoubleClick (object sender, MouseEventArgs e)
        {
            RestoreApplication ();
        }

        void ExitServer_Click (object sender, EventArgs e)
        {
            ExitApplication ();
        }

        private void timer_App_Tick (object sender, EventArgs e)
        {
            PolledComputingModule.PollAll ();
        }

        void MasterModule_StatusChanged (object Sender, ComputingModuleStatusChangedEventArgs evt)
        {
            if (MasterComputingModule.MasterModule.Status == ComputingModuleStatus.cmsIdle)
            {
                ExitApplication ();
            }
        }

        void MasterModule_ModuleStopping (object sender, CancelEventArgs e)
        {
            if (!ConfirmExit ())
            {
                e.Cancel = true;
            }
        }

        #endregion

    }
}
